`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2023/12/20 14:10:24
// Design Name: 
// Module Name: CU
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

module CU(
    input [31:0]order_flag,
    input zero,
    input overflow,
    
    output regfile_write,

    output dmem_write,
    output dmem_read,

    output [18:0] ext_ena,
    output ext16_sign,
    output II_ena,
    output [4:0] alu_op,

    output [1:0] choose_mux_pc,
    output [1:0] choose_mux_od,
    output [1:0] choose_mux_in,

    output choose_mux_out1,
    output choose_mux_out2,
    output choose_mux_ext1

);
wire   add_  =  order_flag [1] ;       //ADD    
wire   addu_ =  order_flag [2] ;       //ADDU
wire   sub_  =  order_flag [3] ;       //SUB
wire   subu_ =  order_flag [4] ;       //SUBU
wire   and_  =  order_flag [5] ;       //AND
wire   or_   =  order_flag [6] ;       //OR
wire   xor_  =  order_flag [7] ;       //XOR
wire   nor_  =  order_flag [8] ;       //NOR
wire   slt_  =  order_flag [9] ;       //SLT
wire   sltu_ =  order_flag [10];       //SLTU
wire   sll_  =  order_flag [11];       //SLL
wire   srl_  =  order_flag [12];       //SRL
wire   sra_  =  order_flag [13];       //SRA
wire   sllv_ =  order_flag [14];       //SLLV
wire   srlv_ =  order_flag [15];       //SRLV
wire   srav_ =  order_flag [16];       //SRAV
wire   jr_   =  order_flag [17];       //JR
wire   addi_ =  order_flag [18];       //ADDI
wire   addiu_=  order_flag [19];       //ADDIU
wire   andi_ =  order_flag [20];       //ANDI
wire   ori_  =  order_flag [21];       //ORI
wire   xori_ =  order_flag [22];       //XORI
wire   lw_   =  order_flag [23];       //LW
wire   sw_   =  order_flag [24];       //SW
wire   beq_  =  order_flag [25];       //BEQ
wire   bne_  =  order_flag [26];       //BNE
wire   slti_ =  order_flag [27];       //SLTI
wire   sltiu_=  order_flag [28];       //SLTIU
wire   lui_  =  order_flag [29];       //LUI
wire   j_    =  order_flag [30];       //J
wire   jal_  =  order_flag [31];       //JAL

assign choose_mux_out1 = (sll_|srl_|sra_) ? 1 : 0;
assign choose_mux_out2 = (addi_|addiu_ | andi_|ori_|xori_|lw_|sw_|slti_|sltiu_|lui_)?1:0;

assign choose_mux_od[0]= (addi_|addiu_|andi_|ori_|xori_|lw_|slti_|sltiu_|lui_)?0:1;
assign choose_mux_od[1]= jal_ ? 1 :0;  

assign choose_mux_ext1 =(slt_ |sltu_)?1:0;

assign choose_mux_pc[1]= ((beq_ & zero )| (bne_ & ~zero)| j_ | jal_) ? 1 : 0; 
assign choose_mux_pc[0] = (jr_ |(beq_&zero)|(bne_ & ~zero))?0:1;

assign choose_mux_in[1] = (slt_|sltu_|lw_|slti_|sltiu_)?0:1;
assign choose_mux_in[0] = (slt_|sltu_|slti_|sltiu_|jal_)?1:0;
assign regfile_write =(jr_|sw_|beq_|bne_|j_)?0:1;
assign dmem_write = sw_?1:0;
assign dmem_read = lw_?1:0;
assign ext_ena[1] = (slt_|sltu_|slti_|sltiu_)?1:0;
assign ext_ena[5] = (sll_|srl_|sra_)?1:0; 
assign ext_ena[16] = (addi_|addiu_|andi_|ori_|xori_|lw_|sw_|slti_|sltiu_|lui_)?1:0;
assign ext_ena[18] = (beq_|bne_)?1:0;
assign ext16_sign = (addi_|addiu_|slti_)? 1 : 0;
assign II_ena = (j_|jal_)?1:0;

assign alu_op[4] = (lui_ | j_|jal_|jr_)?1:0;
assign alu_op[3] = (slt_|sltu_|sll_|srl_|sra_|sllv_|srlv_|srav_)?1:0;
assign alu_op[2] = (and_|andi_|or_|ori_|xor_|xori_|nor_|sra_|sllv_|srlv_|srav_)?1:0;
assign alu_op[1] = (sub_|slti_|subu_|beq_|bne_|sltiu_|xor_|xori_|nor_|sll_|srl_|srlv_|srav_)?1:0;
assign alu_op[0] = (addu_|subu_|beq_|bne_|sltiu_|or_|ori_|nor_|sltu_|srl_|sllv_|srav_|j_|jal_|jr_)?1:0;

endmodule
